package valuecomusa.fijibus.eticket.shorthaul;


import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
//import android.nfc.NfcAdapter;
import android.os.*;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.*;
import com.valuecomusa.Enums;
import com.valuecomusa.bmf.NfcCardInfo;
import org.kobjects.base64.Base64;
import valuecomusa.fijibus.eticket.*;
import valuecomusa.fijibus.eticket.db.shorthaul.BusinessDBHandler;
import valuecomusa.fijibus.eticket.db.shorthaul.GpsDBHandler;
import valuecomusa.fijibus.eticket.dto.GpsCurrentLocationValue;
import valuecomusa.fijibus.eticket.dto.StagesOfRouteValue;
import valuecomusa.fijibus.eticket.ws.*;

import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

public class CheckInV2TapOut extends SunbeamActivity
{
    private static int counter = 1;
    private String TAG = "CheckInV2TapOut";
    //--
    private StagesOfRouteValue currentLocation;

    private double xStageFare;
    private int stageCount;

    private TextView totalFareText;
    private TextView currentBalanceText;
    //private CheckBox printReceipt;

    private BusinessDBHandler db;
    private GpsDBHandler gpsDb;

    private double totalFare;
    private TransactionValue checkInTransaction;
    private List<PassengerTypeValue> passengerTypeList;

    //    private NfcAdapter nfcAdapter;
//    private PendingIntent mPendingIntent;
    private Timer autoSubmit;
    private boolean isAutoSubmit = false;

    private MediaPlayer errorVoice;

    public CheckInV2TapOut()
    {
        TAG = TAG + "." + counter++;
        if (counter > 1000000)
            counter = 1;
    }

    private void InitDataValue()
    {
        currentLocation = null;
        xStageFare = 0;
        stageCount = 1;
    }

    private void fillMemberInfo()
    {
        TextView customerIdText = (TextView) findViewById(R.id.checkout_customer_id);
        customerIdText.setText(WorkingSession.getInstance().currentPassenger.UserName + " ("
                                       + WorkingSession.getInstance().currentPassenger.getFullName() + ")");

        totalFareText.setText(String.valueOf(WorkingSession.getInstance().RoundMoney(totalFare)));
        //--
        currentBalanceText.setText("(current balance: "
                                           + WorkingSession.getInstance().decimalFormat.format(
                WorkingSession.getInstance().currentPassenger.CurrentBalance) + ")");
        //--
        if (WorkingSession.getInstance().currentPassenger.Picture != null &&
                WorkingSession.getInstance().currentPassenger.Picture.length() > 0)
        {
            try
            {
                byte[] imageData = Base64.decode(WorkingSession.getInstance().currentPassenger.Picture);
                Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
                ImageView memberImage = (ImageView) findViewById(R.id.checkout_member_image);
                memberImage.setImageBitmap(bitmap);
            }
            catch (Exception ex)
            {
                Log.e(TAG, "[MemberImage] " + ex.getMessage());
            }
        }
    }

    private double GetPassengerTypeDiscount(String type)
    {
        for (PassengerTypeValue xx : this.passengerTypeList)
        {
            if (xx.Type.toLowerCase().equals(type.toLowerCase()))
                return xx.Discount / 100;
        }
        return 0;
    }

    public void CalcTotalFare()
    {
        if (currentLocation == null)
            return;

        int xCount = currentLocation.StageOrder;

        if (xCount > 1)
        {
            StagesOfRouteValue firstStation = db.getFirstStationOfStageOrder(
                    WorkingSession.getInstance().setupJournal.RouteISN,
                    currentLocation.StageISN,
                    xCount
                                                                            );

            if (firstStation != null
                    && firstStation.BusStationISN == currentLocation.BusStationISN)
            {
                Log.d(TAG, "Check-out at First station of Stage " + xCount);
                xCount = xCount - 1;
            }
        }

        xStageFare = db.getStageFare(checkInTransaction.RouteISN, xCount);
        if (xStageFare < 0)
        {
            WorkingSession.getInstance().ShowToast(
                    CheckInV2TapOut.this,
                    String.format("Could not get Fare of %d Stages", xCount),
                    Toast.LENGTH_SHORT
                                                  );
            xStageFare = 0;
        }
        stageCount = xCount;

        totalFare = 0;

        try
        {
            for (CheckInPassengerValue xx : checkInTransaction.Passengers)
            {
                //Adult, Senior, Child, Disabled, Exempt
                if (xx.Type.toLowerCase().equals("adult"))
                    totalFare += xStageFare * (1 - GetPassengerTypeDiscount("adult"));
                else if (xx.Type.toLowerCase().equals("senior"))
                    totalFare += xStageFare * (1 - GetPassengerTypeDiscount("senior"));
                else if (xx.Type.toLowerCase().equals("child"))
                    totalFare += xStageFare * (1 - GetPassengerTypeDiscount("child"));
                else if (xx.Type.toLowerCase().equals("disabled"))
                    totalFare += xStageFare * (1 - GetPassengerTypeDiscount("disabled"));
                else if (xx.Type.toLowerCase().equals("exempt"))
                    totalFare += xStageFare * (1 - GetPassengerTypeDiscount("exempt"));
                else if (xx.Type.toLowerCase().equals("student"))
                    totalFare += xStageFare * (1 - GetPassengerTypeDiscount("student"));
            }
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[CalcTotalFare] " + ex.getMessage());
        }

        totalFareText.setText(String.valueOf(WorkingSession.getInstance().RoundMoney(totalFare)));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        //--
        Log.d(TAG, "onCreate...");
        // --
        setContentView(R.layout.check_in_v2_tap_out);
        WorkingSession.getInstance().currentActivity = CheckInV2TapOut.this;
        //--
        Log.d(TAG, "[onCreate] WorkingSession.getInstance().setSAMReaderEventListener(samReaderEvent, true);");
        WorkingSession.getInstance().setSAMReaderEventListener(samReaderEvent, true);
        // --
        doCommon();
        InitDataValue();
        //--
        db = new BusinessDBHandler(CheckInV2TapOut.this);
        gpsDb = new GpsDBHandler(CheckInV2TapOut.this);
        //--
//        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
//        mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
//                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        //--
        try
        {
            checkInTransaction = db.getLastCheckInTransaction(
                    WorkingSession.getInstance().currentPassenger.ISN,
                    WorkingSession.getInstance().journalRoute.ISN,
                    WorkingSession.getInstance().journalBus.ISN
                                                             );
        }
        catch (Exception ex)
        {
            Log.d(TAG, "Could not get getLastCheckInTransaction");
        }
        if (checkInTransaction == null)
        {
            WorkingSession.getInstance().ShowErrorDialog(this,
                                                         "Error",
                                                         "Could not get check-in transaction");
            finish();
            return;
        }
        //--
        passengerTypeList = db.getPassengerType();
        if (passengerTypeList == null || passengerTypeList.size() == 0)
        {
            Log.d(TAG, "Could not get Passenger Type discount");
            WorkingSession.getInstance().ShowToast(this,
                                                   "Could not get Passenger Type's discount",
                                                   Toast.LENGTH_LONG);
            return;
        }
        //--

        List<StagesOfRouteValue> stageList = db.getStagesOfRoute(WorkingSession.getInstance().journalRoute.ISN);
        ArrayAdapter<StagesOfRouteValue> stages = new ArrayAdapter<StagesOfRouteValue>(this,
                                                                                       android.R.layout.simple_dropdown_item_1line, stageList);
        //---
        Spinner xx = (Spinner) findViewById(R.id.checkout_current_location);
        xx.setAdapter(stages);
        xx.setOnItemSelectedListener(currentLocationItemClick);
        //---
        Button xxClick = (Button) findViewById(R.id.checkout_current_location_click);
        xxClick.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                Spinner xx = (Spinner) findViewById(R.id.checkout_current_location);
                xx.performClick();
            }
        });
        //---
        totalFareText = (TextView) findViewById(R.id.checkout_total_fare);
        currentBalanceText = (TextView) findViewById(R.id.checkout_current_balance);
        //printReceipt = (CheckBox) findViewById(R.id.checkout_print_receipt);
        //---
        fillMemberInfo();
        //--
        GpsCurrentLocationValue currentGpsLocation = gpsDb.getCurrentLocation(
                WorkingSession.getInstance().setupJournal.ISN);
        if (currentGpsLocation != null)
        {
            Log.d(TAG, String.format("Current location: %d", currentGpsLocation.ClosestStage));
            int idx = -1;
            for (int i = 0; i < stageList.size(); i++)
            {
                Log.d(TAG, String.format("Stage: %d", stageList.get(i).StageISN));
                if (stageList.get(i).StageISN == currentGpsLocation.ClosestStage &&
                        stageList.get(i).BusStationISN == currentGpsLocation.ClosestBusStation)
                {
                    idx = i;
                    break;
                }
            }
            if (idx != -1)
                xx.setSelection(idx);
            else
                xx.setSelection(0);
        }
        else
            xx.setSelection(0);
        //--
        Button submit = (Button) findViewById(R.id.checkout_submit);
        submit.setOnClickListener(onSubmitClick);
        //--
        RegisterTouchEvent();
        //--
        PrepareAutoSubmit();
        //--
        findViewById(R.id.checkout_print_receipt).setVisibility(View.GONE);
    }

    private AdapterView.OnItemSelectedListener currentLocationItemClick = new AdapterView.OnItemSelectedListener()
    {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long rowId)
        {
            StagesOfRouteValue sel = (StagesOfRouteValue) parent.getItemAtPosition(position);

            Log.d(TAG, String.format("Select location: %d - %s", sel.StageISN, sel.StationName));
            currentLocation = sel;
            //--
            CalcTotalFare();
        }

        @Override
        public void onNothingSelected(AdapterView<?> adapterView)
        {
            currentLocation = null;
        }
    };

    private void PrepareAutoSubmit()
    {
        HandlerThread uiThread = new HandlerThread("UIThreadHandler");//to prepare a looper
        uiThread.start();
        uiThreadHandler = new UIThreadHandler(uiThread.getLooper()); //to process UI such as AlertDialog,...

        autoSubmit = new Timer();
        autoSubmit.scheduleAtFixedRate(
                autoSubmitTask,
                0,
                1000);
        isAutoSubmit = true;
    }

    @Override
    protected void onStart()
    {
        super.onStart();
        Log.d(TAG, "onStart...");
    }

    @Override
    protected void onResume()
    {
        Log.d(TAG, "[onResume] ....");
        super.onResume();
        Log.d(TAG, "[onCreate] WorkingSession.getInstance().setSAMReaderEventListener(samReaderEvent, false);");
        WorkingSession.getInstance().setSAMReaderEventListener(samReaderEvent, false);
    }

    @Override
    protected void onPause()
    {
        Log.d(TAG, "[onPause] ....");
        super.onPause();

        WorkingSession.getInstance().RestoreBackupSAMReaderEventListener();
    }

    @Override
    protected void onDestroy()
    {
        Log.d(TAG, "[onDestroy] ....");
        super.onDestroy();
        if (autoSubmit != null)
            autoSubmit.cancel();
        isAutoSubmit = false;
        //--
        if (errorVoice != null)
        {
            errorVoice.stop();
            errorVoice = null;
        }

        WorkingSession.getInstance().RestoreBackupSAMReaderEventListener();
    }

    private boolean UpdateTransaction2CheckOut()
    {
        if (checkInTransaction == null)
        {
            WorkingSession.getInstance().ShowErrorDialog(
                    CheckInV2TapOut.this,
                    "Error",
                    "Check-in transaction not found");
            return false;
        }
        if (currentLocation == null)
        {
            WorkingSession.getInstance().ShowErrorDialog(
                    CheckInV2TapOut.this,
                    "Error",
                    "Please select destination");
            return false;
        }

        //double checkInFare = checkInTransaction.FareAmount;
        checkInTransaction.FareAmount = WorkingSession.getInstance().RoundMoney(totalFare);
        checkInTransaction.Destination = currentLocation.StationName;
        checkInTransaction.CheckOutDate = new Date();
        GpsCurrentLocationValue currentGpsLocation = gpsDb.getCurrentLocation(
                WorkingSession.getInstance().setupJournal.ISN
                                                                             );
        if (currentGpsLocation != null)
        {
            checkInTransaction.Latitude2 = currentGpsLocation.Latitude;
            checkInTransaction.Longitude2 = currentGpsLocation.Longitude;

            //replace [@checkout] in description with destination stage
            String x = checkInTransaction.Description;
            x = x.replace("[@checkout]",
                          String.format(", Check-out near %s", getClosestStationName(currentGpsLocation)));
            checkInTransaction.Description = x;
        }

        int x = db.updateTransactionCheckOut(checkInTransaction);
        if (x < 0)
        {
            WorkingSession.getInstance().ShowToast(
                    CheckInV2TapOut.this,
                    "Update transaction failed",
                    Toast.LENGTH_SHORT
                                                  );
            return false;
        }

        //----------
        WaitCardReaderOpenAndTapped();

        if (WorkingSession.getInstance().IsSmartCardTapped())
        {
            Log.e(TAG, "[UpdateTransaction2CheckOut] Write check-out to card...");
            NfcCardInfo xx = WorkingSession.getInstance().SAMCheckOut(
                    WorkingSession.getInstance().getLastTappedCardType(),
                    (int) (checkInTransaction.FareAmount*100),
                    (float) checkInTransaction.Latitude,
                    (float) checkInTransaction.Longitude,
                    (float) checkInTransaction.Latitude2,
                    (float) checkInTransaction.Longitude2);
            if (xx != null)
                Log.e(TAG, "[UpdateTransaction2CheckOut] Write check-out to card successful");
            else
                Log.e(TAG, "[UpdateTransaction2CheckOut] Unable to write check-out to card");
        }

        WorkingSession.getInstance().ShowToast(
                CheckInV2TapOut.this,
                "Update transaction successful",
                Toast.LENGTH_SHORT
                                              );

        //--update customer balance
        WorkingSession.getInstance().currentPassenger.CurrentBalance -= WorkingSession.getInstance().RoundMoney(totalFare);
        x = db.updateMemberBalance(
                WorkingSession.getInstance().currentPassenger.ISN,
                WorkingSession.getInstance().currentPassenger.CurrentBalance);
        if (x < 0)
        {
            WorkingSession.getInstance().ShowToast(
                    CheckInV2TapOut.this,
                    "Update customer balance failed",
                    Toast.LENGTH_SHORT
                                                  );
            return false;
        }
        WorkingSession.getInstance().ShowToast(
                CheckInV2TapOut.this,
                "Update customer balance successful",
                Toast.LENGTH_SHORT
                                              );

        return true;
    }

    private boolean WaitCardReaderOpenAndTapped()
    {
//        if(WorkingSession.getInstance().getSAM_NfcCardTapped() == -1)
//            WorkingSession.getInstance().OpenSAMCardReader(-1); //open with last information
        Log.d(TAG, "[WaitCardReaderOpenAndTapped] Waiting for card tapped in 10s");
        Date lastTest = new Date();
        long diffInSec = 0;
        try
        {
            do
            {
                Thread.sleep(200);
                long diffInMs = (new Date()).getTime() - lastTest.getTime();
                diffInSec = (long) TimeUnit.MILLISECONDS.toSeconds(diffInMs);
                lastTest = new Date();
            }
            while (!WorkingSession.getInstance().IsSmartCardTapped() && diffInSec < 10); //waiting for 10s
        }
        catch (Exception ex)
        {
            Log.e(TAG, "[WaitCardReaderOpenAndTapped] Exception: " + ex);
            ex.printStackTrace();
            return false;
        }
        if (diffInSec >= 10)
            return false;
        return true;
    }

    private String CreateReceiptContent(TransactionValue xx)
    {
        /*Date date = new Date();
        String receiptDate = Utilities.DateToString(date, "dd.MM.yyyy");
        String receiptTime = Utilities.DateToString(date, "hh:mm a");

        String content = "Powered by: BulamyFiji (BMF)"
                + "\nSunbeam Transport (Fiji) Ltd"
                + "\nLautoka, Fiji Islands"
                + "\nTIN #: 35846990930"
                + "\n********************************"
                + "\nFrom     : " + currentLocation.StationName
                + "\nStages   : " + stageCount
                + "\nDate     : " + receiptDate
                + "\nDept Time: " + receiptTime
                + "\nNo. Passn: " + String.valueOf(xx.Passengers.size())
                + "\nFare     : " + WorkingSession.getInstance().decimalFormat.format(xStageFare)
                + "\nTotal    : " + WorkingSession.getInstance().decimalFormat.format(totalFare)
                + "\n---"
                + "\nPymt type: " + xx.Type
                + "\nTran ID  : " + xx.TransactionID
                + "\nVehicle  : " + WorkingSession.getInstance().journalBus.BusNumber
                + "\nConductor: " + WorkingSession.getInstance().loggedInConductor.UserName
                + "\n---"
                + "\nCustomer : " + WorkingSession.getInstance().currentPassenger.getFullName()
                + "\nACC #    : xxxx" + WorkingSession.getInstance().currentPassenger.CardNumber.substring(
                            WorkingSession.getInstance().currentPassenger.CardNumber.length()-4)
                + "\nBalance  : " + WorkingSession.getInstance().decimalFormat.format(
                            WorkingSession.getInstance().currentPassenger.CurrentBalance)
                + "\n********************************"
                + "\nRetain this receipt till end of journey"
                + "\n--------------------------------\n";
        return content;*/
        Date date = new Date();
        String receiptDate = Utilities.DateToString(date, "dd/MM/yyyy");
        String receiptTime = Utilities.DateToString(date, "hh:mm a");

        String content = Utilities.StringAlignCenter(48, "BulaMy(Fiji) - BMF etikite  ") //+ "\n"
                + Utilities.StringAlignCenter(48, "BMF Make It Your Choice")
                + Utilities.StringAlignCenter(48, "www.bulamyfiji.com")
                + "\n\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "Entry: " + checkInTransaction.Origination,
                                                 "Bus Reg.: " + WorkingSession.getInstance().journalBus.BusNumber
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "Exit: " + currentLocation.StationName,
                                                 "Driver: " + WorkingSession.getInstance().journalDriver.FullName
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "Stages: " + stageCount,
                                                 "Company: DeeCees Fiji Ltd"
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "Fare: " + WorkingSession.getInstance().decimalFormat.format(xStageFare),
                                                 "TIN: 12683467161"
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "No. PAX: " + String.valueOf(xx.Passengers.size()),
                                                 "Transaction ID: " + xx.TransactionID
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "Total: " + String.valueOf(WorkingSession.getInstance().RoundMoney(totalFare)),
                                                 "Issued: " + receiptDate + " " + receiptTime
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "ACCT Name: " + WorkingSession.getInstance().currentPassenger.getFullName(),
                                                 "Mode: " + xx.Type
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "ACCT #: " + WorkingSession.getInstance().currentPassenger.CardNumber,
                                                 "TopUp Amount: " + WorkingSession.getInstance().decimalFormat.format(xx.TopUpAmount)
                                                ) + "\n"
                + Utilities.StringAlignLeftRight(48,
                                                 "Balance: " + WorkingSession.getInstance().decimalFormat.format(
                                                         WorkingSession.getInstance().currentPassenger.CurrentBalance),
                                                 " "
                                                ) + "\n"
                + "\nPlease Keep Receipt For Your Records\n\n";

        return content;
    }

    private boolean PrintReceipt(TransactionValue xx)
    {
        if (!WorkingSession.getInstance().printReceipt)
            return false;
        //--
        String receipt = CreateReceiptContent(xx);

        int rs = WorkingSession.getInstance().PreparePrintReceiptWifi(CheckInV2TapOut.this, receipt, printReceiptCallback);

        if (rs == Declarations.NO_WIFI_PRINTER_SETUP)
            WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this, "No printer selected. Please setup one.", Toast.LENGTH_LONG);
        else if (rs == Declarations.PRINT_RECEIPT_ERROR)
        {
            WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this, "Print receipt failed.", Toast.LENGTH_LONG);
        }
        else
        {
            WorkingSession.getInstance().ShowToast(
                    CheckInV2TapOut.this,
                    "Print receipt...",
                    Toast.LENGTH_SHORT
                                                  );
        }
        return rs == Declarations.PRINT_RECEIPT_WAITING;
    }

    private final Handler printReceiptCallback = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                case Declarations.WIFI_PRINTER_CONNECTED:
                    WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this,
                                                           "Printer connected", Toast.LENGTH_SHORT);
                    WorkingSession.getInstance().PrintReceipt();
                    break;
                case Declarations.WIFI_PRINTER_CONNECTED_ERR:
                    WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this,
                                                           "Unable connect to printer", Toast.LENGTH_SHORT);
                    uiThreadHandler.sendEmptyMessage(UIThreadHandler.DO_BACK_PRESS);
                    break;
                case Declarations.WIFI_PRINTER_SEND_FAILED:
                    WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this,
                                                           "Unable send data to printer", Toast.LENGTH_SHORT);
                    uiThreadHandler.sendEmptyMessage(UIThreadHandler.DO_BACK_PRESS);
                    break;
                case Declarations.PRINT_RECEIPT_SUCCESSFUL:
                    WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this,
                                                           "Print receipt successful", Toast.LENGTH_SHORT);
                    uiThreadHandler.sendEmptyMessage(UIThreadHandler.DO_BACK_PRESS);
                    break;
            }
        }
    };

    OnClickListener onSubmitClick = new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            String file2Play = "";
            if (WorkingSession.getInstance().IsSmartCardTapped())
            {
                doCheckOut(null);
            }
            else
            {
                file2Play = "process-error.mp3";
                WorkingSession.getInstance().ShowErrorDialog(
                        CheckInV2TapOut.this,
                        "Card Missing",
                        "Please insert your card into Card Reader."
                                                            );
                File mp3File = new File(Environment.getExternalStorageDirectory() +
                                                Declarations.ShortHaul_sdCard_Folder + file2Play);
                if (!mp3File.exists())
                {
                    errorVoice = null;
                    WorkingSession.getInstance().ShowToast(
                            CheckInV2TapOut.this,
                            "File not found. " + mp3File.getAbsolutePath(),
                            Toast.LENGTH_SHORT
                                                          );
                }
                else
                {
                    //isPlayVoiceCompleted = false;
                    errorVoice = Utilities.PlayMedia(
                            CheckInV2TapOut.this,
                            file2Play);
                }
            }

        }
    };

	/*private MediaPlayer.OnCompletionListener onPlayErrorVoiceCompleted = new MediaPlayer.OnCompletionListener()
    {
		@Override
		public void onCompletion(MediaPlayer mp)
		{
			Log.d(TAG, "[onPlayErrorVoiceCompleted]...");
			isPlayVoiceCompleted = true;
		}
	};*/


    //private boolean isPlayVoiceCompleted = true;
    private boolean doCheckOut(String cardNumber)
    {
        if (!UpdateTransaction2CheckOut())
            return false;

        //-------------------TEST-------------------
        WorkingSession.getInstance().transactionCount++;
        //-------------------TEST-------------------


        String file2Play = "";

        if (WorkingSession.getInstance().currentPassenger.CurrentBalance < 0)
        {
            file2Play = "negative-balance.mp3";
        }
        else
        {
            file2Play = "tapout.mp3";
        }

        File mp3File = new File(Environment.getExternalStorageDirectory() +
                                        Declarations.ShortHaul_sdCard_Folder + file2Play);
        if (!mp3File.exists())
        {
            errorVoice = null;
            WorkingSession.getInstance().ShowToast(
                    CheckInV2TapOut.this,
                    "File not found. " + mp3File.getAbsolutePath(),
                    Toast.LENGTH_SHORT
                                                  );
        }
        else
        {
            //isPlayVoiceCompleted = false;
            errorVoice = Utilities.PlayMedia(
                    CheckInV2TapOut.this,
                    file2Play);
        }

        //if(gpsDb.getCurrentLocation(WorkingSession.getInstance().setupJournal.ISN)==null){
        //  WorkingSession.getInstance().SAMCheckOut((float)checkInTransaction.FareAmount , 0,0,0,0);
        //}else {

        //WorkingSession.getInstance().SAMCheckOut((float) checkInTransaction.FareAmount,
        //      (float) checkInTransaction.Latitude,
        //    (float) checkInTransaction.Longitude,
        //  (float) checkInTransaction.Latitude2,
        //(float) checkInTransaction.Longitude2);
        //}

        if (!PrintReceipt(checkInTransaction))
        {
            if (cardNumber == null || cardNumber.length() == 0)
                uiThreadHandler.sendEmptyMessage(UIThreadHandler.DO_BACK_PRESS);
            else
            {
                backToMainWithInputMember(cardNumber);
                Message msg = new Message();
                msg.what = UIThreadHandler.DO_BACK_PRESS;
                msg.obj = cardNumber;
                //uiThreadHandler.sendEmptyMessage(UIThreadHandler.DO_BACK_PRESS);
                uiThreadHandler.sendMessage(msg);
            }
        }
        //--
        return true;
    }

    @Override
    public void onBackPressed()
    {
        Intent next = new Intent(CheckInV2TapOut.this, Main.class);

        next.putExtra("INPUT_DIRECT_CHECK_IN", 0);
        if (Main.getInstance() != null)
            Main.getInstance().setIntent(next);

        //super.onBackPressed();
        finish();
    }

    private void backToMainWithInputMember(String cardNumber)
    {
        Intent mainScreen = new Intent(CheckInV2TapOut.this, Main.class);
        mainScreen.putExtra("INPUT_CUSTOMER", cardNumber);

        if (Main.getInstance() != null)
            Main.getInstance().setIntent(mainScreen);
        finish();
    }

    private UIThreadHandler uiThreadHandler;

    private final class UIThreadHandler extends android.os.Handler
    {
        private final String TAG = "CheckOutUIThreadHandler";
        public static final int MSG_COUNT_DOWN = 0x10;
        private int currentCountDownValue = Declarations.TAP_OUT_TIMEOUT_SECONDS;
        public static final int DO_BACK_PRESS = 0x14;
        private String cardNumber = "";

        public UIThreadHandler(Looper lp)
        {
            super(lp);
        }

        @Override
        public void handleMessage(Message msg)
        {
            try
            {
                switch (msg.what)
                {
                    case UIThreadHandler.MSG_COUNT_DOWN:
                    {
                        Log.d(TAG, "Countdown: " + currentCountDownValue);
                        ShowToast("Submitting...");
                        currentCountDownValue--;
                        if (currentCountDownValue <= 0)
                        {
                            Log.d(TAG, "Cancel autoSubmit timer");
                            autoSubmit.cancel();
                            isAutoSubmit = false;
                            doCheckOut(null);
                        }

                        break;
                    }
                    case DO_BACK_PRESS:
                        Thread.sleep(500);
                        cardNumber = "";
                        if (msg.obj != null)
                            cardNumber = String.valueOf(msg.obj);

                        while (errorVoice != null && errorVoice.isPlaying())// !isPlayVoiceCompleted)
                            Thread.sleep(100);
                        if (cardNumber != null && cardNumber.length() > 0)
                        {
                            runOnUiThread(new Runnable()
                            {
                                @Override
                                public void run()
                                {
                                    backToMainWithInputMember(cardNumber);
                                }
                            });
                        }
                        else
                        {
                            runOnUiThread(new Runnable()
                            {
                                @Override
                                public void run()
                                {
                                    onBackPressed();
                                }
                            });
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                Log.e(TAG, String.format("[MSG:%d] %s", msg.what, ex.toString()));
            }
        }

        private void ShowToast(String text)
        {
            ShowToast(text, Toast.LENGTH_SHORT);
        }

        private void ShowToast(String text, int duration)
        {
            if (isMyFriendActive())
            {
                WorkingSession.getInstance().ShowToast(CheckInV2TapOut.this, text, duration);
            }
        }

        private Toast currentToast;
    }

    private boolean isMyFriendActive()
    {
        ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
        // get the info from the currently running task
        List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);

        /*Log.d(TAG, "CURRENT Activity :: "
                + taskInfo.get(0).topActivity.getClassName());*/
        String activeName = taskInfo.get(0).topActivity.getClassName();
        if (activeName.contains("valuecomusa.fijibus.eticket.shorthaul.CheckInV2TapOut"))
            return true;
        return false;
    }

    private TimerTask autoSubmitTask = new TimerTask()
    {
        @Override
        public void run()
        {
            uiThreadHandler.sendEmptyMessage(UIThreadHandler.MSG_COUNT_DOWN);
        }
    };

    private View.OnTouchListener onTouch = new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent)
        {
            Log.d(TAG, "onTouch: " + view.getId());
            if (view.isEnabled() && autoSubmit != null)
            {
                Log.d(TAG, "Cancel autoSubmit timer");
                autoSubmit.cancel();
                autoSubmit = null;
                isAutoSubmit = false;
            }
            return false;
        }
    };

    private void RegisterTouchEvent()
    {
        findViewById(R.id.checkout_current_location).setOnTouchListener(onTouch);
        findViewById(R.id.checkout_current_location_click).setOnTouchListener(onTouch);
        findViewById(R.id.checkout_print_receipt).setOnTouchListener(onTouch);
        findViewById(R.id.checkout_submit).setOnTouchListener(onTouch);
    }

//    @Override
//    public void onNewIntent(Intent intent)
//    {
//        String action = intent.getAction();
//        Log.d(TAG, String.format("[onNewIntent] Action: %s", action));
//
//        if (action != null && (action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)
//                || action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
//            && currentLocation != null && !isAutoSubmit)
//        {
//            /*String[] result = Utilities.readNFCTagContentAndSerial(CheckInV2TapOut.this, intent);
//            //--result[0] = TagSerial, result[1] = Tag content
//            if (result == null || result.length < 2)
//                return;
//
//            if(result[1].length() == 0)
//            {
//                WorkingSession.getInstance().ShowToast(
//                        CheckInV2TapOut.this,
//                        "Invalid NFC Tag content",
//                        Toast.LENGTH_SHORT
//                );
//            }
//
//            MemberValue cust = db.getMemberByCard(result[1], result[0]);
//
//            if (cust != null)
//            {
//                //--Submit current check in
//                //--Go back Main and check in again with new customer
//                doCheckOut(cust.CardNumber);
//            }
//            else
//            {
//                //Utilities.PlayMedia(CheckInV2TapOut.this, "C.mp3");
//                WorkingSession.getInstance().ShowErrorDialog(
//                        CheckInV2TapOut.this,
//                        "Error",
//                        "Could not get information of Card#: " + result[1]
//                );
//            }*/
//        }
//        else
//        {
//            Log.d(TAG, "Action: " + action + ", current location not ready");
//        }
//    }

    private String getClosestStationName(GpsCurrentLocationValue currentGpsLocation)
    {
        if (currentGpsLocation == null)
            return "";

        List<StagesOfRouteValue> stageList = db.getStagesOfRoute(WorkingSession.getInstance().journalRoute.ISN);
        int idx = -1;
        for (int i = 0; i < stageList.size(); i++)
        {
            Log.d(TAG, String.format("Stage: %d", stageList.get(i).StageISN));
            if (stageList.get(i).StageISN == currentGpsLocation.ClosestStage &&
                    stageList.get(i).BusStationISN == currentGpsLocation.ClosestBusStation)
            {
                idx = i;
                break;
            }
        }
        if (idx != -1)
            return stageList.get(idx).StationName;
        return "";
    }

    //added by lhdung Dec.2014
    private Enums.CardProvider tappedCardType;
    private WorkingSession.SAMReaderEvent samReaderEvent = new WorkingSession.SAMReaderEvent()
    {
        @Override
        public void OnReaderStateChange(String state)
        {
            Log.d(TAG, "[SAMReaderEvent.OnReaderStateChange] " + state);
            WorkingSession.getInstance().ShowToast(
                    CheckInV2TapOut.this,
                    "Card Reader " + state,
                    Toast.LENGTH_SHORT
            );
        }

        @Override
        public void OnSAMSlotStateChange(int slot, String state)
        {
            Log.d(TAG, String.format("[SAMReaderEvent.OnSAMSlotStateChange] Slot  %d state %s", slot, state));

        }

        @Override
        public void OnSmartCardInteraction(Enums.CardProvider cardProvider, int status, String description)
        {

            if (status == Declarations.SMART_CARD_STATE_PRESENT) //tap in
            {
                Log.d(TAG, String.format("[SAMReaderEvent.OnSmartCardInteraction] %s tapped. Card status  %d, %s",
                        cardProvider.toString(), status, description));
                //do process tap in
                tappedCardType = cardProvider;
            }
            else //may be tap out
            {
                Log.d(TAG, String.format("[SAMReaderEvent.OnSmartCardInteraction] %s removed. Card status  %d, %s",
                        cardProvider.toString(), status, description));
            }
        }
    };
}
